Packages
library(plyr)
library(tidyverse)
library(here)
library(geojsonR)
library(janitor)
library(knitr)
library(lubridate)
library(mapview)
library(gbfs)
library(sf)
library(tmap)
library(tidycensus)
library(dplyr)
library(conflicted)
library(plotly)
conflicts_prefer(here::here)
[conflicted] Removing existing preference.[conflicted] Will prefer here::here over any other package.
conflicts_prefer(dplyr::rename)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::rename over any other package.
conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::filter over any other package.
conflicts_prefer(dplyr::mutate)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::mutate over any other package.
Reading the files.
Metro Station Entrances to map the location of metro, boarding data
to show how many people are using the metro station, and bikeshare to
show the number of people riding bikes.
All data is from the month September because there are no major
holidays, the weather is still decent enough for people to ride bikes,
and the number of tourists/ pleasure bike riders are reduced.
For the purpose of this project, we plan on focusing on the
commuters, and plan on creating more bike locations to better suit the
number of commuters.
metro <- FROM_GeoJson(here('data_raw', 'Metro_Station_Entrances_in_DC.geojson'))
metroRiders <- read.csv(here( 'Boardings by Route Table_Full Data_data.csv'))
metroLoc <- read.csv(here('data_raw', 'Metro_Stations_Regional.csv'))
sept_raw <- read_csv(here( '202309-capitalbikeshare-tripdata.csv'))
<<<<<<< HEAD
Rows: 450090 Columns: 13── Column specification ───────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): ride_id, rideable_type, start_station_name, end_station_name, member_casual
dbl (6): start_station_id, end_station_id, start_lat, start_lng, end_lat, end_lng
=======
<<<<<<< HEAD
Rows: 450090 Columns: 13── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): ride_id, rideable_type, start_station_name, end_station_name, member_casual
dbl (6): start_station_id, end_station_id, start_lat, start_lng, end_lat, end_lng
=======
Rows: 450090 Columns: 13-- Column specification ------------------------------
Delimiter: ","
chr (5): ride_id, rideable_type, start_station_na...
dbl (6): start_station_id, end_station_id, start_...
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
dttm (2): started_at, ended_at
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
neigh = st_read(here("data_raw", "DC_Health_Planning_Neighborhoods.geojson")) %>% clean_names()
<<<<<<< HEAD
Reading layer `DC_Health_Planning_Neighborhoods' from data source
`C:\DATASCIENCE\basta-dataforskare\data_raw\DC_Health_Planning_Neighborhoods.geojson' using driver `GeoJSON'
=======
<<<<<<< HEAD
Reading layer `DC_Health_Planning_Neighborhoods' from data source
`C:\Users\avery\Documents\ds241\ds241_f23\basta-dataforskare\basta-dataforskare\data_raw\DC_Health_Planning_Neighborhoods.geojson'
=======
Reading layer `DC_Health_Planning_Neighborhoods' from data source `C:\Users\benne\OneDrive\Desktop\Intro to Data Science\WORKSPACE\DS241\basta-dataforskare\data_raw\DC_Health_Planning_Neighborhoods.geojson'
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
using driver `GeoJSON'
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Simple feature collection with 51 features and 8 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -77.11976 ymin: 38.79165 xmax: -76.9094 ymax: 38.99556
Geodetic CRS: WGS 84
Cleaning Data
This filters the data so we are only getting entries for the weekdays
and not the weekends, appending location variables to station names, and
combining repeat stations with a summed amount of entries.
#metroLoc = metroLoc |>
#rename("X" = "ï..X")
metroAddy <- subset(metroLoc, select = c(NAME, ADDRESS, X, Y))|>
rename("Station" = "NAME", "Lon" = "X", "Lat" = "Y")
metroRiders$Time.Period = NULL
metroRiders$Day.of.Week = NULL
metroRiders$Holiday = NULL
metroRiders$Month = NULL
metroRiders$Year = NULL
metroRiders$Avg.Daily.Entries.Rounded = NULL
#metroRiders = metroRiders |>
#rename("Station" = "ï..Station")
metroR1 <- metroRiders |>
filter(Servicetype == "Weekday") |>
ddply("Station", numcolwise(sum))
METRO <- merge(x = metroR1, y = metroAddy, by = "Station")
glimpse(METRO)
<<<<<<< HEAD
Rows: 86
Columns: 5
$ Station <chr> "Anacostia", "Arlington Cemetery", "Ashburn", "Ballston-MU", "Benning Road", "Bethesda", "Bra…
$ Entries <int> 62365, 16111, 25199, 114875, 31518, 102933, 45638, 47644, 85141, 23630, 101604, 10032, 57042,…
$ ADDRESS <chr> "1101 HOWARD ROAD SE, WASHINGTON, DC", "1000 NORTH MEMORIAL DRIVE, ARLINGTON, VA", "43625-A C…
$ Lon <dbl> -76.99537, -77.06281, -77.49154, -77.11317, -76.93837, -77.09413, -77.05367, -76.91147, -76.9…
$ Lat <dbl> 38.86297, 38.88469, 39.00529, 38.88219, 38.89098, 38.98440, 38.81415, 38.82645, 38.93322, 38.…
=======
<<<<<<< HEAD
Rows: 86
Columns: 5
$ Station <chr> "Anacostia", "Arlington Cemetery", "Ashburn", "Ballston-MU", "Benning Road", "Bethesda", "Braddock Road",…
$ Entries <int> 62365, 16111, 25199, 114875, 31518, 102933, 45638, 47644, 85141, 23630, 101604, 10032, 57042, 47500, 3734…
$ ADDRESS <chr> "1101 HOWARD ROAD SE, WASHINGTON, DC", "1000 NORTH MEMORIAL DRIVE, ARLINGTON, VA", "43625-A CROSON LN, AS…
$ Lon <dbl> -76.99537, -77.06281, -77.49154, -77.11317, -76.93837, -77.09413, -77.05367, -76.91147, -76.99454, -76.91…
$ Lat <dbl> 38.86297, 38.88469, 39.00529, 38.88219, 38.89098, 38.98440, 38.81415, 38.82645, 38.93322, 38.88947, 38.88…
=======
Rows: 86
Columns: 5
$ Station <chr> "Anacostia", "Arlington Cemetery", "~
$ Entries <int> 62365, 16111, 25199, 114875, 31518, ~
$ ADDRESS <chr> "1101 HOWARD ROAD SE, WASHINGTON, DC~
$ Lon <dbl> -76.99537, -77.06281, -77.49154, -77~
$ Lat <dbl> 38.86297, 38.88469, 39.00529, 38.882~
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Cleaning bike data
bikeR1 is the data set originated from September Bikeshare data. It
is filtered to keep the columns “started at”, “start lat” and
“start_lng”. Na.omit gets rid of everything null, and mutate adds the
date to when each bike ride started.
bikeR2 is a further filtering of bikeR1 where coordinates are added
so we can map out the bike riders starting location.
bikeR3 is the new data set where bikeR2 and neigh are joined.
bikeR1 = sept_raw %>% select(started_at, start_lat, start_lng) %>% na.omit() %>% mutate(start_date=as.Date(started_at)) %>% select(start_date, start_lat, start_lng)
bikeR2 = bikeR1 %>% st_as_sf(coords=c("start_lng", "start_lat"), crs=4326)
st_crs(neigh$geometry[1])
Coordinate Reference System:
User input: WGS 84
wkt:
GEOGCRS["WGS 84",
DATUM["World Geodetic System 1984",
ELLIPSOID["WGS 84",6378137,298.257223563,
LENGTHUNIT["metre",1]]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
AXIS["geodetic latitude (Lat)",north,
ORDER[1],
ANGLEUNIT["degree",0.0174532925199433]],
AXIS["geodetic longitude (Lon)",east,
ORDER[2],
ANGLEUNIT["degree",0.0174532925199433]],
ID["EPSG",4326]]
bikeR3 = bikeR2 %>% st_join(neigh)
#code for possible future mapping
#df1_s_sf = df1_s %>% st_as_sf(coords =c("start_lng", "start_lat"), crs = 4326)
Metro Map
The first part of this code chunk is converting the metro data frame
into a spatial data frame.
MetroMap2 is a filtration of MetroMap that joins the data set “neigh”
and omits any null values. Then a variable ‘code’ is added to the
numcolwise. There are 50 ‘codes’ created in this process. Then from
those codes, we will determine rideship for both bikes and metro.
MetroMap <- st_as_sf(METRO, coords = c("Lon", "Lat"), crs =4326)
MetroMap2 <- MetroMap %>%
st_join(neigh) %>% na.omit() %>%
ddply("code", numcolwise(sum))
More Filtering
neigh1 is the new data frame of “neigh” where code and geometry are
the chosen variables to be kept.
bike R4 is a further filtration of bikeR3, where start date, code,
geometry is kept and geometry column is dropped.
bikeR5 is another filter of neigh1, where bikeR4 is added (joined).
Additionally, each of the weekend dates are removed from the data set as
we chose to only look at weekday data.
neigh1 = neigh %>% select(code, geometry)
bikeR4 = bikeR3 %>% select(start_date, code, geometry) %>% st_drop_geometry()
bikeR5 = neigh1 %>% full_join(bikeR4) %>% filter(start_date != as.Date('2023-09-02')) %>% filter(start_date != as.Date('2023-09-03')) %>% filter(start_date != as.Date('2023-09-09')) %>% filter(start_date != as.Date('2023-09-10')) %>% filter(start_date != as.Date('2023-09-16')) %>% filter(start_date != as.Date('2023-09-17')) %>% filter(start_date != as.Date('2023-09-23')) %>% filter(start_date != as.Date('2023-09-24')) %>% filter(start_date != as.Date('2023-09-30'))
Joining with `by = join_by(code)`
And More!
bikeR6 is a nre data frame where we took the bike data from set
bikeR5. bikeR6 has 51 codes and they are listed as observations. All
null values are ommitted.
bikeR7 takes the data from bikeR6 and keeps the code as well as
frequency and renames it to bike_freq.
#plot(neigh)
bikeR6 = data.frame(table(bikeR5$code)) %>% rename(code=Var1) %>% full_join(bikeR5) %>% select(code, Freq, geometry) %>% distinct() %>% na.omit()
Joining with `by = join_by(code)`
bikeR7 = bikeR6 %>% select (code, Freq) %>% rename(bike_freq = Freq)
MetroMap3 = MetroMap2 %>% select(Entries, code) %>% rename(metro_freq = Entries)
metro_bike_df = bikeR7 %>% full_join(MetroMap3) %>% mutate(metro_freq = replace_na(metro_freq, 0))
Joining with `by = join_by(code)`
#bikeR7 = bikeR5 %>% count(code, start_date)
#plot(bikeR6)
Last One!
bikeR8 takes bikeR6 and keeps the code and frequency. It also creates
a column called bike because all the data in this set is from bike
riders. We will use this column later when we make our visual.
MetroMap4 continues the filtration of MetroMap2 where entries (later
renamed to freq) and code are kept. Every data in this set is given the
variable ‘metro’ as they represent a metro rider.
bikeR8 = bikeR6 %>% select (code, Freq) %>% rename(freq = Freq) %>% mutate(transport = 'bike')
MetroMap4 = MetroMap2 %>% select(Entries, code) %>% rename(freq = Entries) %>% mutate(transport = 'metro')
code = c("N1", "N10", "N11", "N14", "N15", "N16", "N2", "N20", "N21", "N22", "N26", "N27", "N28", "N3", "N32", "N33", "N34", "N36", "N37", "N4", "N40", "N41", "N45", "N46", "N47", "N49", "N5", "N50", "N51", "N6", "N8")
freq = c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
transport = c('metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro')
metroExtra = data.frame(code, freq, transport)
MetroMap4 = MetroMap4 %>% rbind(metroExtra)
metro_bike_df2 = bikeR8 %>% full_join(MetroMap4)
Joining with `by = join_by(code, freq, transport)`
Mapping Metro
This is a simple visual of the metro station locations in DC.
entrances=st_read(here("Metro_Station_Entrances_in_DC.geojson")) %>% clean_names()
<<<<<<< HEAD
Reading layer `Metro_Station_Entrances_in_DC' from data source
`C:\DATASCIENCE\basta-dataforskare\Metro_Station_Entrances_in_DC.geojson' using driver `GeoJSON'
=======
<<<<<<< HEAD
Reading layer `Metro_Station_Entrances_in_DC' from data source
`C:\Users\avery\Documents\ds241\ds241_f23\basta-dataforskare\basta-dataforskare\Metro_Station_Entrances_in_DC.geojson'
=======
Reading layer `Metro_Station_Entrances_in_DC' from data source `C:\Users\benne\OneDrive\Desktop\Intro to Data Science\WORKSPACE\DS241\basta-dataforskare\Metro_Station_Entrances_in_DC.geojson'
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
using driver `GeoJSON'
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Simple feature collection with 113 features and 23 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -77.08577 ymin: 38.84465 xmax: -76.93472 ymax: 38.97578
Geodetic CRS: WGS 84
class(entrances)
[1] "sf" "data.frame"
plot(entrances)
Warning: plotting the first 10 out of 23 attributes; use max.plot = 23 to plot all
<<<<<<< HEAD

=======
<<<<<<< HEAD

=======

>>>>>>> 36321748959043dd50b7a89e48066d2758840639
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Mapping Bike Data
We create a gg plot of the data from above. The combined data set of
metro and bike riders (metro_bike_df2). We wanted to visualize the
number of people who are riding the metro vs using bikes in each of the
‘codes’.
<<<<<<< HEAD
ggplot(metro_bike_df2, aes(fill=transport, y=freq, x=code)) + geom_bar(position='dodge', stat='identity')

=======
charts <- ggplot(metro_bike_df2, aes(fill=transport, y=freq, x=code)) + geom_bar(position='dodge', stat='identity')
ggplotly(charts)
<<<<<<< HEAD
=======
NA
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Recommednation:
Based on the data comaprisons of metro entries adn bike entries, we
would recommend that the bikeshare group look into increasing the amount
of bike stations in neighboorhoods: n1, n2, n3, n4, n6, n8, n10, n11,
n14, n15, n16, n20, n21, n22, n26, n27, n28, n32, n33, n34, n36, n37,
n40, n41, n45, n46, n47, n49, n50, n51.
<<<<<<< HEAD
LS0tDQp0aXRsZTogIkZpbmFsIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBQYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShnZW9qc29uUikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KGdiZnMpDQpsaWJyYXJ5KHNmKSANCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpsaWJyYXJ5KHBsb3RseSkNCmNvbmZsaWN0c19wcmVmZXIoaGVyZTo6aGVyZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OnJlbmFtZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6Om11dGF0ZSkNCg0KYGBgDQoNCiMjIFJlYWRpbmcgdGhlIGZpbGVzLg0KDQpNZXRybyBTdGF0aW9uIEVudHJhbmNlcyB0byBtYXAgdGhlIGxvY2F0aW9uIG9mIG1ldHJvLCBib2FyZGluZyBkYXRhIHRvIHNob3cgaG93IG1hbnkgcGVvcGxlIGFyZSB1c2luZyB0aGUgbWV0cm8gc3RhdGlvbiwgYW5kIGJpa2VzaGFyZSB0byBzaG93IHRoZSBudW1iZXIgb2YgcGVvcGxlIHJpZGluZyBiaWtlcy4NCg0KQWxsIGRhdGEgaXMgZnJvbSB0aGUgbW9udGggU2VwdGVtYmVyIGJlY2F1c2UgdGhlcmUgYXJlIG5vIG1ham9yIGhvbGlkYXlzLCB0aGUgd2VhdGhlciBpcyBzdGlsbCBkZWNlbnQgZW5vdWdoIGZvciBwZW9wbGUgdG8gcmlkZSBiaWtlcywgYW5kIHRoZSBudW1iZXIgb2YgdG91cmlzdHMvIHBsZWFzdXJlIGJpa2UgcmlkZXJzIGFyZSByZWR1Y2VkLg0KDQpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBwcm9qZWN0LCB3ZSBwbGFuIG9uIGZvY3VzaW5nIG9uIHRoZSBjb21tdXRlcnMsIGFuZCBwbGFuIG9uIGNyZWF0aW5nIG1vcmUgYmlrZSBsb2NhdGlvbnMgdG8gYmV0dGVyIHN1aXQgdGhlIG51bWJlciBvZiBjb21tdXRlcnMuDQoNCmBgYHtyfQ0KbWV0cm8gPC0gRlJPTV9HZW9Kc29uKGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25fRW50cmFuY2VzX2luX0RDLmdlb2pzb24nKSkNCm1ldHJvUmlkZXJzIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ0JvYXJkaW5ncyBieSBSb3V0ZSBUYWJsZV9GdWxsIERhdGFfZGF0YS5jc3YnKSkNCm1ldHJvTG9jIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25zX1JlZ2lvbmFsLmNzdicpKSANCg0Kc2VwdF9yYXcgPC0gcmVhZF9jc3YoaGVyZSgnZGF0YV9yYXcnLCAnMjAyMzA5LWNhcGl0YWxiaWtlc2hhcmUtdHJpcGRhdGEuY3N2JykpDQoNCm5laWdoID0gc3RfcmVhZChoZXJlKCJkYXRhX3JhdyIsICJEQ19IZWFsdGhfUGxhbm5pbmdfTmVpZ2hib3Job29kcy5nZW9qc29uIikpICU+JSBjbGVhbl9uYW1lcygpDQoNCmBgYA0KDQojIyBDbGVhbmluZyBEYXRhDQoNClRoaXMgZmlsdGVycyB0aGUgZGF0YSBzbyB3ZSBhcmUgb25seSBnZXR0aW5nIGVudHJpZXMgZm9yIHRoZSB3ZWVrZGF5cyBhbmQgbm90IHRoZSB3ZWVrZW5kcywgYXBwZW5kaW5nIGxvY2F0aW9uIHZhcmlhYmxlcyB0byBzdGF0aW9uIG5hbWVzLCBhbmQgY29tYmluaW5nIHJlcGVhdCBzdGF0aW9ucyB3aXRoIGEgc3VtbWVkIGFtb3VudCBvZiBlbnRyaWVzLg0KDQpgYGB7cn0NCiNtZXRyb0xvYyA9IG1ldHJvTG9jIHw+IA0KICAjcmVuYW1lKCJYIiA9ICLDry4uWCIpDQoNCm1ldHJvQWRkeSA8LSBzdWJzZXQobWV0cm9Mb2MsIHNlbGVjdCA9IGMoTkFNRSwgQUREUkVTUywgWCwgWSkpfD4NCiAgcmVuYW1lKCJTdGF0aW9uIiA9ICJOQU1FIiwgIkxvbiIgPSAiWCIsICJMYXQiID0gIlkiKQ0KDQptZXRyb1JpZGVycyRUaW1lLlBlcmlvZCA9IE5VTEwNCm1ldHJvUmlkZXJzJERheS5vZi5XZWVrID0gTlVMTA0KbWV0cm9SaWRlcnMkSG9saWRheSA9IE5VTEwNCm1ldHJvUmlkZXJzJE1vbnRoID0gTlVMTA0KbWV0cm9SaWRlcnMkWWVhciA9IE5VTEwNCm1ldHJvUmlkZXJzJEF2Zy5EYWlseS5FbnRyaWVzLlJvdW5kZWQgPSBOVUxMDQoNCiNtZXRyb1JpZGVycyA9IG1ldHJvUmlkZXJzIHw+DQogI3JlbmFtZSgiU3RhdGlvbiIgPSAiw68uLlN0YXRpb24iKQ0KDQptZXRyb1IxIDwtIG1ldHJvUmlkZXJzIHw+DQogIGZpbHRlcihTZXJ2aWNldHlwZSA9PSAiV2Vla2RheSIpIHw+DQogIGRkcGx5KCJTdGF0aW9uIiwgbnVtY29sd2lzZShzdW0pKQ0KDQpNRVRSTyA8LSBtZXJnZSh4ID0gbWV0cm9SMSwgeSA9IG1ldHJvQWRkeSwgYnkgPSAiU3RhdGlvbiIpDQoNCmdsaW1wc2UoTUVUUk8pDQoNCmBgYA0KDQpDbGVhbmluZyBiaWtlIGRhdGENCg0KYGBge3J9DQpiaWtlUjEgPSBzZXB0X3JhdyAlPiUgc2VsZWN0KHN0YXJ0ZWRfYXQsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKSAlPiUgbmEub21pdCgpICU+JSBtdXRhdGUoc3RhcnRfZGF0ZT1hcy5EYXRlKHN0YXJ0ZWRfYXQpKSAlPiUgc2VsZWN0KHN0YXJ0X2RhdGUsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKQ0KDQpiaWtlUjIgPSBiaWtlUjEgJT4lIHN0X2FzX3NmKGNvb3Jkcz1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycz00MzI2KQ0KDQpzdF9jcnMobmVpZ2gkZ2VvbWV0cnlbMV0pDQoNCmJpa2VSMyA9IGJpa2VSMiAlPiUgc3Rfam9pbihuZWlnaCkNCg0KDQogDQojY29kZSBmb3IgcG9zc2libGUgZnV0dXJlIG1hcHBpbmcgDQojZGYxX3Nfc2YgPSBkZjFfcyAlPiUgc3RfYXNfc2YoY29vcmRzID1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycyA9IDQzMjYpDQpgYGANCg0KYGBge3J9DQpNZXRyb01hcCA8LSBzdF9hc19zZihNRVRSTywgY29vcmRzID0gYygiTG9uIiwgIkxhdCIpLCBjcnMgPTQzMjYpDQoNCk1ldHJvTWFwMiA8LSBNZXRyb01hcCAlPiUNCiAgc3Rfam9pbihuZWlnaCkgJT4lIG5hLm9taXQoKSAlPiUNCiAgZGRwbHkoImNvZGUiLCBudW1jb2x3aXNlKHN1bSkpDQpgYGANCg0KDQpgYGB7cn0NCg0KbmVpZ2gxID0gbmVpZ2ggJT4lIHNlbGVjdChjb2RlLCBnZW9tZXRyeSkNCg0KYmlrZVI0ID0gYmlrZVIzICU+JSBzZWxlY3Qoc3RhcnRfZGF0ZSwgY29kZSwgZ2VvbWV0cnkpICU+JSBzdF9kcm9wX2dlb21ldHJ5KCkNCg0KYmlrZVI1ID0gbmVpZ2gxICU+JSBmdWxsX2pvaW4oYmlrZVI0KSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wOScpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xMCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yNCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0zMCcpKQ0KYGBgDQoNCmBgYHtyfQ0KI3Bsb3QobmVpZ2gpDQoNCmJpa2VSNiA9IGRhdGEuZnJhbWUodGFibGUoYmlrZVI1JGNvZGUpKSAlPiUgcmVuYW1lKGNvZGU9VmFyMSkgJT4lIGZ1bGxfam9pbihiaWtlUjUpICU+JSBzZWxlY3QoY29kZSwgRnJlcSwgZ2VvbWV0cnkpICU+JSBkaXN0aW5jdCgpICU+JSBuYS5vbWl0KCkNCg0KYmlrZVI3ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoYmlrZV9mcmVxID0gRnJlcSkNCg0KTWV0cm9NYXAzID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShtZXRyb19mcmVxID0gRW50cmllcykNCg0KbWV0cm9fYmlrZV9kZiA9IGJpa2VSNyAlPiUgZnVsbF9qb2luKE1ldHJvTWFwMykgJT4lIG11dGF0ZShtZXRyb19mcmVxID0gcmVwbGFjZV9uYShtZXRyb19mcmVxLCAwKSkNCg0KI2Jpa2VSNyA9IGJpa2VSNSAlPiUgY291bnQoY29kZSwgc3RhcnRfZGF0ZSkNCg0KI3Bsb3QoYmlrZVI2KQ0KYGBgDQoNCmBgYHtyfQ0KYmlrZVI4ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoZnJlcSA9IEZyZXEpICU+JSBtdXRhdGUodHJhbnNwb3J0ID0gJ2Jpa2UnKQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDIgJT4lIHNlbGVjdChFbnRyaWVzLCBjb2RlKSAlPiUgcmVuYW1lKGZyZXEgPSBFbnRyaWVzKSAlPiUgbXV0YXRlKHRyYW5zcG9ydCA9ICdtZXRybycpDQoNCmNvZGUgPSBjKCJOMSIsICJOMTAiLCAiTjExIiwgIk4xNCIsICJOMTUiLCAiTjE2IiwgIk4yIiwgIk4yMCIsICJOMjEiLCAiTjIyIiwgIk4yNiIsICJOMjciLCAiTjI4IiwgIk4zIiwgIk4zMiIsICJOMzMiLCAiTjM0IiwgIk4zNiIsICJOMzciLCAiTjQiLCAiTjQwIiwgIk40MSIsICJONDUiLCAiTjQ2IiwgIk40NyIsICJONDkiLCAiTjUiLCAiTjUwIiwgIk41MSIsICJONiIsICJOOCIpDQoNCmZyZXEgPSBjKDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDApDQoNCnRyYW5zcG9ydCA9IGMoJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJykNCg0KbWV0cm9FeHRyYSA9IGRhdGEuZnJhbWUoY29kZSwgZnJlcSwgdHJhbnNwb3J0KQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDQgJT4lIHJiaW5kKG1ldHJvRXh0cmEpDQoNCm1ldHJvX2Jpa2VfZGYyID0gYmlrZVI4ICU+JSBmdWxsX2pvaW4oTWV0cm9NYXA0KQ0KDQpgYGANCg0KDQojIyBNYXBwaW5nIE1ldHJvDQoNCmBgYHtyfQ0KZW50cmFuY2VzPXN0X3JlYWQoaGVyZSgiTWV0cm9fU3RhdGlvbl9FbnRyYW5jZXNfaW5fREMuZ2VvanNvbiIpKSAlPiUgY2xlYW5fbmFtZXMoKQ0KDQpjbGFzcyhlbnRyYW5jZXMpDQoNCnBsb3QoZW50cmFuY2VzKQ0KYGBgDQoNCiMjIE1hcHBpbmcgQmlrZSBEYXRhDQoNCg0KYGBge3J9DQpjaGFydHMgPC0gZ2dwbG90KG1ldHJvX2Jpa2VfZGYyLCBhZXMoZmlsbD10cmFuc3BvcnQsIHk9ZnJlcSwgeD1jb2RlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0nZG9kZ2UnLCBzdGF0PSdpZGVudGl0eScpDQoNCmdncGxvdGx5KGNoYXJ0cykNCmBgYA0KDQojIyBSZWNvbW1lZG5hdGlvbjoNCkJhc2VkIG9uIHRoZSBkYXRhIGNvbWFwcmlzb25zIG9mIG1ldHJvIGVudHJpZXMgYWRuIGJpa2UgZW50cmllcywgd2Ugd291bGQgcmVjb21tZW5kIHRoYXQgdGhlIGJpa2VzaGFyZSBncm91cCBsb29rIGludG8gaW5jcmVhc2luZyB0aGUgYW1vdW50IG9mIGJpa2Ugc3RhdGlvbnMgaW4gbmVpZ2hib29yaG9vZHM6IG4xLCBuMiwgbjMsIG40LCBuNiwgbjgsIG4xMCwgbjExLCBuMTQsIG4xNSwgbjE2LCBuMjAsIG4yMSwgbjIyLCBuMjYsIG4yNywgbjI4LCBuMzIsIG4zMywgbjM0LCBuMzYsIG4zNywgbjQwLCBuNDEsIG40NSwgbjQ2LCBuNDcsIG40OSwgbjUwLCBuNTEu
=======
<<<<<<< HEAD
LS0tDQp0aXRsZTogIkZpbmFsIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBQYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShnZW9qc29uUikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KGdiZnMpDQpsaWJyYXJ5KHNmKSANCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpjb25mbGljdHNfcHJlZmVyKGhlcmU6OmhlcmUpDQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjpyZW5hbWUpDQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjpmaWx0ZXIpDQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjptdXRhdGUpDQoNCmBgYA0KDQojIyBSZWFkaW5nIHRoZSBmaWxlcy4NCg0KTWV0cm8gU3RhdGlvbiBFbnRyYW5jZXMgdG8gbWFwIHRoZSBsb2NhdGlvbiBvZiBtZXRybywgYm9hcmRpbmcgZGF0YSB0byBzaG93IGhvdyBtYW55IHBlb3BsZSBhcmUgdXNpbmcgdGhlIG1ldHJvIHN0YXRpb24sIGFuZCBiaWtlc2hhcmUgdG8gc2hvdyB0aGUgbnVtYmVyIG9mIHBlb3BsZSByaWRpbmcgYmlrZXMuDQoNCkFsbCBkYXRhIGlzIGZyb20gdGhlIG1vbnRoIFNlcHRlbWJlciBiZWNhdXNlIHRoZXJlIGFyZSBubyBtYWpvciBob2xpZGF5cywgdGhlIHdlYXRoZXIgaXMgc3RpbGwgZGVjZW50IGVub3VnaCBmb3IgcGVvcGxlIHRvIHJpZGUgYmlrZXMsIGFuZCB0aGUgbnVtYmVyIG9mIHRvdXJpc3RzLyBwbGVhc3VyZSBiaWtlIHJpZGVycyBhcmUgcmVkdWNlZC4NCg0KRm9yIHRoZSBwdXJwb3NlIG9mIHRoaXMgcHJvamVjdCwgd2UgcGxhbiBvbiBmb2N1c2luZyBvbiB0aGUgY29tbXV0ZXJzLCBhbmQgcGxhbiBvbiBjcmVhdGluZyBtb3JlIGJpa2UgbG9jYXRpb25zIHRvIGJldHRlciBzdWl0IHRoZSBudW1iZXIgb2YgY29tbXV0ZXJzLg0KDQpgYGB7cn0NCm1ldHJvIDwtIEZST01fR2VvSnNvbihoZXJlKCdkYXRhX3JhdycsICdNZXRyb19TdGF0aW9uX0VudHJhbmNlc19pbl9EQy5nZW9qc29uJykpDQptZXRyb1JpZGVycyA8LSByZWFkLmNzdihoZXJlKCAnQm9hcmRpbmdzIGJ5IFJvdXRlIFRhYmxlX0Z1bGwgRGF0YV9kYXRhLmNzdicpKQ0KbWV0cm9Mb2MgPC0gcmVhZC5jc3YoaGVyZSgnZGF0YV9yYXcnLCAnTWV0cm9fU3RhdGlvbnNfUmVnaW9uYWwuY3N2JykpIA0KDQpzZXB0X3JhdyA8LSByZWFkX2NzdihoZXJlKCAnMjAyMzA5LWNhcGl0YWxiaWtlc2hhcmUtdHJpcGRhdGEuY3N2JykpDQoNCm5laWdoID0gc3RfcmVhZChoZXJlKCJkYXRhX3JhdyIsICJEQ19IZWFsdGhfUGxhbm5pbmdfTmVpZ2hib3Job29kcy5nZW9qc29uIikpICU+JSBjbGVhbl9uYW1lcygpDQoNCmBgYA0KDQojIyBDbGVhbmluZyBEYXRhDQoNClRoaXMgZmlsdGVycyB0aGUgZGF0YSBzbyB3ZSBhcmUgb25seSBnZXR0aW5nIGVudHJpZXMgZm9yIHRoZSB3ZWVrZGF5cyBhbmQgbm90IHRoZSB3ZWVrZW5kcywgYXBwZW5kaW5nIGxvY2F0aW9uIHZhcmlhYmxlcyB0byBzdGF0aW9uIG5hbWVzLCBhbmQgY29tYmluaW5nIHJlcGVhdCBzdGF0aW9ucyB3aXRoIGEgc3VtbWVkIGFtb3VudCBvZiBlbnRyaWVzLg0KDQpgYGB7cn0NCiMjIG1ldHJvTG9jID0gbWV0cm9Mb2MgfD4gDQogICMjIHJlbmFtZSgiWCIgPSAiw68uLlgiKQ0KDQptZXRyb0FkZHkgPC0gc3Vic2V0KG1ldHJvTG9jLCBzZWxlY3QgPSBjKE5BTUUsIEFERFJFU1MsIFgsIFkpKXw+DQogIHJlbmFtZSgiU3RhdGlvbiIgPSAiTkFNRSIsICJMb24iID0gIlgiLCAiTGF0IiA9ICJZIikNCg0KbWV0cm9SaWRlcnMkVGltZS5QZXJpb2QgPSBOVUxMDQptZXRyb1JpZGVycyREYXkub2YuV2VlayA9IE5VTEwNCm1ldHJvUmlkZXJzJEhvbGlkYXkgPSBOVUxMDQptZXRyb1JpZGVycyRNb250aCA9IE5VTEwNCm1ldHJvUmlkZXJzJFllYXIgPSBOVUxMDQptZXRyb1JpZGVycyRBdmcuRGFpbHkuRW50cmllcy5Sb3VuZGVkID0gTlVMTA0KDQojIyBtZXRyb1JpZGVycyA9IG1ldHJvUmlkZXJzIHw+DQogIyMgcmVuYW1lKCJTdGF0aW9uIiA9ICLDry4uU3RhdGlvbiIpDQoNCm1ldHJvUjEgPC0gbWV0cm9SaWRlcnMgfD4NCiAgZmlsdGVyKFNlcnZpY2V0eXBlID09ICJXZWVrZGF5IikgfD4NCiAgZGRwbHkoIlN0YXRpb24iLCBudW1jb2x3aXNlKHN1bSkpDQoNCk1FVFJPIDwtIG1lcmdlKHggPSBtZXRyb1IxLCB5ID0gbWV0cm9BZGR5LCBieSA9ICJTdGF0aW9uIikNCg0KZ2xpbXBzZShNRVRSTykNCg0KYGBgDQoNCiMjIENsZWFuaW5nIGJpa2UgZGF0YQ0KDQpiaWtlUjEgaXMgdGhlIGRhdGEgc2V0IG9yaWdpbmF0ZWQgZnJvbSBTZXB0ZW1iZXIgQmlrZXNoYXJlIGRhdGEuIEl0IGlzIGZpbHRlcmVkIHRvIGtlZXAgdGhlIGNvbHVtbnMgInN0YXJ0ZWQgYXQiLCAic3RhcnQgbGF0IiBhbmQgInN0YXJ0X2xuZyIuIE5hLm9taXQgZ2V0cyByaWQgb2YgZXZlcnl0aGluZyBudWxsLCBhbmQgbXV0YXRlIGFkZHMgdGhlIGRhdGUgdG8gd2hlbiBlYWNoIGJpa2UgcmlkZSBzdGFydGVkLg0KDQpiaWtlUjIgaXMgYSBmdXJ0aGVyIGZpbHRlcmluZyBvZiBiaWtlUjEgd2hlcmUgY29vcmRpbmF0ZXMgYXJlIGFkZGVkIHNvIHdlIGNhbiBtYXAgb3V0IHRoZSBiaWtlIHJpZGVycyBzdGFydGluZyBsb2NhdGlvbi4NCg0KYmlrZVIzIGlzIHRoZSBuZXcgZGF0YSBzZXQgd2hlcmUgYmlrZVIyIGFuZCBuZWlnaCBhcmUgam9pbmVkLiANCg0KYGBge3J9DQpiaWtlUjEgPSBzZXB0X3JhdyAlPiUgc2VsZWN0KHN0YXJ0ZWRfYXQsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKSAlPiUgbmEub21pdCgpICU+JSBtdXRhdGUoc3RhcnRfZGF0ZT1hcy5EYXRlKHN0YXJ0ZWRfYXQpKSAlPiUgc2VsZWN0KHN0YXJ0X2RhdGUsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKQ0KDQpiaWtlUjIgPSBiaWtlUjEgJT4lIHN0X2FzX3NmKGNvb3Jkcz1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycz00MzI2KQ0KDQpzdF9jcnMobmVpZ2gkZ2VvbWV0cnlbMV0pDQoNCmJpa2VSMyA9IGJpa2VSMiAlPiUgc3Rfam9pbihuZWlnaCkNCg0KDQogDQojY29kZSBmb3IgcG9zc2libGUgZnV0dXJlIG1hcHBpbmcgDQojZGYxX3Nfc2YgPSBkZjFfcyAlPiUgc3RfYXNfc2YoY29vcmRzID1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycyA9IDQzMjYpDQpgYGANCg0KDQojIyBNZXRybyBNYXANCg0KVGhlIGZpcnN0IHBhcnQgb2YgdGhpcyBjb2RlIGNodW5rIGlzIGNvbnZlcnRpbmcgdGhlIG1ldHJvIGRhdGEgZnJhbWUgaW50byBhIHNwYXRpYWwgZGF0YSBmcmFtZS4gDQoNCk1ldHJvTWFwMiBpcyBhIGZpbHRyYXRpb24gb2YgTWV0cm9NYXAgdGhhdCBqb2lucyB0aGUgZGF0YSBzZXQgIm5laWdoIiBhbmQgb21pdHMgYW55IG51bGwgdmFsdWVzLiBUaGVuIGEgdmFyaWFibGUgJ2NvZGUnIGlzIGFkZGVkIHRvIHRoZSBudW1jb2x3aXNlLiBUaGVyZSBhcmUgNTAgJ2NvZGVzJyBjcmVhdGVkIGluIHRoaXMgcHJvY2Vzcy4gVGhlbiBmcm9tIHRob3NlIGNvZGVzLCB3ZSB3aWxsIGRldGVybWluZSByaWRlc2hpcCBmb3IgYm90aCBiaWtlcyBhbmQgbWV0cm8uDQoNCmBgYHtyfQ0KTWV0cm9NYXAgPC0gc3RfYXNfc2YoTUVUUk8sIGNvb3JkcyA9IGMoIkxvbiIsICJMYXQiKSwgY3JzID00MzI2KQ0KDQpNZXRyb01hcDIgPC0gTWV0cm9NYXAgJT4lDQogIHN0X2pvaW4obmVpZ2gpICU+JSBuYS5vbWl0KCkgJT4lDQogIGRkcGx5KCJjb2RlIiwgbnVtY29sd2lzZShzdW0pKQ0KYGBgDQoNCg0KIyMgTW9yZSBGaWx0ZXJpbmcNCg0KbmVpZ2gxIGlzIHRoZSBuZXcgZGF0YSBmcmFtZSBvZiAibmVpZ2giIHdoZXJlIGNvZGUgYW5kIGdlb21ldHJ5IGFyZSB0aGUgY2hvc2VuIHZhcmlhYmxlcyB0byBiZSBrZXB0Lg0KDQpiaWtlIFI0IGlzIGEgZnVydGhlciBmaWx0cmF0aW9uIG9mIGJpa2VSMywgd2hlcmUgc3RhcnQgZGF0ZSwgY29kZSwgZ2VvbWV0cnkgaXMga2VwdCBhbmQgZ2VvbWV0cnkgY29sdW1uIGlzIGRyb3BwZWQuDQoNCmJpa2VSNSBpcyBhbm90aGVyIGZpbHRlciBvZiBuZWlnaDEsIHdoZXJlIGJpa2VSNCBpcyBhZGRlZCAoam9pbmVkKS4gQWRkaXRpb25hbGx5LCBlYWNoIG9mIHRoZSB3ZWVrZW5kIGRhdGVzIGFyZSByZW1vdmVkIGZyb20gdGhlIGRhdGEgc2V0IGFzIHdlIGNob3NlIHRvIG9ubHkgbG9vayBhdCB3ZWVrZGF5IGRhdGEuDQoNCmBgYHtyfQ0KDQpuZWlnaDEgPSBuZWlnaCAlPiUgc2VsZWN0KGNvZGUsIGdlb21ldHJ5KQ0KDQpiaWtlUjQgPSBiaWtlUjMgJT4lIHNlbGVjdChzdGFydF9kYXRlLCBjb2RlLCBnZW9tZXRyeSkgJT4lIHN0X2Ryb3BfZ2VvbWV0cnkoKQ0KDQpiaWtlUjUgPSBuZWlnaDEgJT4lIGZ1bGxfam9pbihiaWtlUjQpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTAyJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTAzJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTA5JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTEwJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTE2JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTE3JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTIzJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTI0JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTMwJykpDQpgYGANCiMjIEFuZCBNb3JlIQ0KDQpiaWtlUjYgaXMgYSBucmUgZGF0YSBmcmFtZSB3aGVyZSB3ZSB0b29rIHRoZSBiaWtlIGRhdGEgZnJvbSBzZXQgYmlrZVI1LiBiaWtlUjYgaGFzIDUxIGNvZGVzIGFuZCB0aGV5IGFyZSBsaXN0ZWQgYXMgb2JzZXJ2YXRpb25zLiBBbGwgbnVsbCB2YWx1ZXMgYXJlIG9tbWl0dGVkLg0KDQpiaWtlUjcgdGFrZXMgdGhlIGRhdGEgZnJvbSBiaWtlUjYgYW5kIGtlZXBzIHRoZSBjb2RlIGFzIHdlbGwgYXMgZnJlcXVlbmN5IGFuZCByZW5hbWVzIGl0IHRvIGJpa2VfZnJlcS4gDQoNCmBgYHtyfQ0KI3Bsb3QobmVpZ2gpDQoNCmJpa2VSNiA9IGRhdGEuZnJhbWUodGFibGUoYmlrZVI1JGNvZGUpKSAlPiUgcmVuYW1lKGNvZGU9VmFyMSkgJT4lIGZ1bGxfam9pbihiaWtlUjUpICU+JSBzZWxlY3QoY29kZSwgRnJlcSwgZ2VvbWV0cnkpICU+JSBkaXN0aW5jdCgpICU+JSBuYS5vbWl0KCkNCg0KYmlrZVI3ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoYmlrZV9mcmVxID0gRnJlcSkNCg0KTWV0cm9NYXAzID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShtZXRyb19mcmVxID0gRW50cmllcykNCg0KbWV0cm9fYmlrZV9kZiA9IGJpa2VSNyAlPiUgZnVsbF9qb2luKE1ldHJvTWFwMykgJT4lIG11dGF0ZShtZXRyb19mcmVxID0gcmVwbGFjZV9uYShtZXRyb19mcmVxLCAwKSkNCg0KI2Jpa2VSNyA9IGJpa2VSNSAlPiUgY291bnQoY29kZSwgc3RhcnRfZGF0ZSkNCg0KI3Bsb3QoYmlrZVI2KQ0KYGBgDQojIyBMYXN0IE9uZSENCg0KYmlrZVI4IHRha2VzIGJpa2VSNiBhbmQga2VlcHMgdGhlIGNvZGUgYW5kIGZyZXF1ZW5jeS4gSXQgYWxzbyBjcmVhdGVzIGEgY29sdW1uIGNhbGxlZCBiaWtlIGJlY2F1c2UgYWxsIHRoZSBkYXRhIGluIHRoaXMgc2V0IGlzIGZyb20gYmlrZSByaWRlcnMuIFdlIHdpbGwgdXNlIHRoaXMgY29sdW1uIGxhdGVyIHdoZW4gd2UgbWFrZSBvdXIgdmlzdWFsLiANCg0KTWV0cm9NYXA0IGNvbnRpbnVlcyB0aGUgZmlsdHJhdGlvbiBvZiBNZXRyb01hcDIgd2hlcmUgZW50cmllcyAobGF0ZXIgcmVuYW1lZCB0byBmcmVxKSBhbmQgY29kZSBhcmUga2VwdC4gRXZlcnkgZGF0YSBpbiB0aGlzIHNldCBpcyBnaXZlbiB0aGUgdmFyaWFibGUgJ21ldHJvJyBhcyB0aGV5IHJlcHJlc2VudCBhIG1ldHJvIHJpZGVyLg0KDQpgYGB7cn0NCmJpa2VSOCA9IGJpa2VSNiAlPiUgc2VsZWN0IChjb2RlLCBGcmVxKSAlPiUgcmVuYW1lKGZyZXEgPSBGcmVxKSAlPiUgbXV0YXRlKHRyYW5zcG9ydCA9ICdiaWtlJykNCg0KTWV0cm9NYXA0ID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShmcmVxID0gRW50cmllcykgJT4lIG11dGF0ZSh0cmFuc3BvcnQgPSAnbWV0cm8nKQ0KDQpjb2RlID0gYygiTjEiLCAiTjEwIiwgIk4xMSIsICJOMTQiLCAiTjE1IiwgIk4xNiIsICJOMiIsICJOMjAiLCAiTjIxIiwgIk4yMiIsICJOMjYiLCAiTjI3IiwgIk4yOCIsICJOMyIsICJOMzIiLCAiTjMzIiwgIk4zNCIsICJOMzYiLCAiTjM3IiwgIk40IiwgIk40MCIsICJONDEiLCAiTjQ1IiwgIk40NiIsICJONDciLCAiTjQ5IiwgIk41IiwgIk41MCIsICJONTEiLCAiTjYiLCAiTjgiKQ0KDQpmcmVxID0gYygwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwKQ0KDQp0cmFuc3BvcnQgPSBjKCdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycpDQoNCm1ldHJvRXh0cmEgPSBkYXRhLmZyYW1lKGNvZGUsIGZyZXEsIHRyYW5zcG9ydCkNCg0KTWV0cm9NYXA0ID0gTWV0cm9NYXA0ICU+JSByYmluZChtZXRyb0V4dHJhKQ0KDQptZXRyb19iaWtlX2RmMiA9IGJpa2VSOCAlPiUgZnVsbF9qb2luKE1ldHJvTWFwNCkNCg0KYGBgDQoNCg0KIyMgTWFwcGluZyBNZXRybw0KDQpUaGlzIGlzIGEgc2ltcGxlIHZpc3VhbCBvZiB0aGUgbWV0cm8gc3RhdGlvbiBsb2NhdGlvbnMgaW4gREMuDQoNCmBgYHtyfQ0KZW50cmFuY2VzPXN0X3JlYWQoaGVyZSgiTWV0cm9fU3RhdGlvbl9FbnRyYW5jZXNfaW5fREMuZ2VvanNvbiIpKSAlPiUgY2xlYW5fbmFtZXMoKQ0KDQpjbGFzcyhlbnRyYW5jZXMpDQoNCnBsb3QoZW50cmFuY2VzKQ0KYGBgDQoNCiMjIE1hcHBpbmcgQmlrZSBEYXRhDQoNCldlIGNyZWF0ZSBhIGdnIHBsb3Qgb2YgdGhlIGRhdGEgZnJvbSBhYm92ZS4gVGhlIGNvbWJpbmVkIGRhdGEgc2V0IG9mIG1ldHJvIGFuZCBiaWtlIHJpZGVycyAobWV0cm9fYmlrZV9kZjIpLiBXZSB3YW50ZWQgdG8gdmlzdWFsaXplIHRoZSBudW1iZXIgb2YgcGVvcGxlIHdobyBhcmUgcmlkaW5nIHRoZSBtZXRybyB2cyB1c2luZyBiaWtlcyBpbiBlYWNoIG9mIHRoZSAnY29kZXMnLiANCg0KYGBge3J9DQoNCmdncGxvdChtZXRyb19iaWtlX2RmMiwgYWVzKGZpbGw9dHJhbnNwb3J0LCB5PWZyZXEsIHg9Y29kZSkpICsgZ2VvbV9iYXIocG9zaXRpb249J2RvZGdlJywgc3RhdD0naWRlbnRpdHknKQ0KDQpgYGANCg0K
=======
LS0tDQp0aXRsZTogIkZpbmFsIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBQYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShnZW9qc29uUikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KGdiZnMpDQpsaWJyYXJ5KHNmKSANCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpsaWJyYXJ5KHBsb3RseSkNCmNvbmZsaWN0c19wcmVmZXIoaGVyZTo6aGVyZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OnJlbmFtZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6Om11dGF0ZSkNCg0KYGBgDQoNCiMjIFJlYWRpbmcgdGhlIGZpbGVzLg0KDQpNZXRybyBTdGF0aW9uIEVudHJhbmNlcyB0byBtYXAgdGhlIGxvY2F0aW9uIG9mIG1ldHJvLCBib2FyZGluZyBkYXRhIHRvIHNob3cgaG93IG1hbnkgcGVvcGxlIGFyZSB1c2luZyB0aGUgbWV0cm8gc3RhdGlvbiwgYW5kIGJpa2VzaGFyZSB0byBzaG93IHRoZSBudW1iZXIgb2YgcGVvcGxlIHJpZGluZyBiaWtlcy4NCg0KQWxsIGRhdGEgaXMgZnJvbSB0aGUgbW9udGggU2VwdGVtYmVyIGJlY2F1c2UgdGhlcmUgYXJlIG5vIG1ham9yIGhvbGlkYXlzLCB0aGUgd2VhdGhlciBpcyBzdGlsbCBkZWNlbnQgZW5vdWdoIGZvciBwZW9wbGUgdG8gcmlkZSBiaWtlcywgYW5kIHRoZSBudW1iZXIgb2YgdG91cmlzdHMvIHBsZWFzdXJlIGJpa2UgcmlkZXJzIGFyZSByZWR1Y2VkLg0KDQpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBwcm9qZWN0LCB3ZSBwbGFuIG9uIGZvY3VzaW5nIG9uIHRoZSBjb21tdXRlcnMsIGFuZCBwbGFuIG9uIGNyZWF0aW5nIG1vcmUgYmlrZSBsb2NhdGlvbnMgdG8gYmV0dGVyIHN1aXQgdGhlIG51bWJlciBvZiBjb21tdXRlcnMuDQoNCmBgYHtyfQ0KbWV0cm8gPC0gRlJPTV9HZW9Kc29uKGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25fRW50cmFuY2VzX2luX0RDLmdlb2pzb24nKSkNCm1ldHJvUmlkZXJzIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ0JvYXJkaW5ncyBieSBSb3V0ZSBUYWJsZV9GdWxsIERhdGFfZGF0YS5jc3YnKSkNCm1ldHJvTG9jIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25zX1JlZ2lvbmFsLmNzdicpKSANCg0Kc2VwdF9yYXcgPC0gcmVhZF9jc3YoaGVyZSgnZGF0YV9yYXcnLCAnMjAyMzA5LWNhcGl0YWxiaWtlc2hhcmUtdHJpcGRhdGEuY3N2JykpDQoNCm5laWdoID0gc3RfcmVhZChoZXJlKCJkYXRhX3JhdyIsICJEQ19IZWFsdGhfUGxhbm5pbmdfTmVpZ2hib3Job29kcy5nZW9qc29uIikpICU+JSBjbGVhbl9uYW1lcygpDQoNCmBgYA0KDQojIyBDbGVhbmluZyBEYXRhDQoNClRoaXMgZmlsdGVycyB0aGUgZGF0YSBzbyB3ZSBhcmUgb25seSBnZXR0aW5nIGVudHJpZXMgZm9yIHRoZSB3ZWVrZGF5cyBhbmQgbm90IHRoZSB3ZWVrZW5kcywgYXBwZW5kaW5nIGxvY2F0aW9uIHZhcmlhYmxlcyB0byBzdGF0aW9uIG5hbWVzLCBhbmQgY29tYmluaW5nIHJlcGVhdCBzdGF0aW9ucyB3aXRoIGEgc3VtbWVkIGFtb3VudCBvZiBlbnRyaWVzLg0KDQpgYGB7cn0NCiNtZXRyb0xvYyA9IG1ldHJvTG9jIHw+IA0KICAjcmVuYW1lKCJYIiA9ICLDry4uWCIpDQoNCm1ldHJvQWRkeSA8LSBzdWJzZXQobWV0cm9Mb2MsIHNlbGVjdCA9IGMoTkFNRSwgQUREUkVTUywgWCwgWSkpfD4NCiAgcmVuYW1lKCJTdGF0aW9uIiA9ICJOQU1FIiwgIkxvbiIgPSAiWCIsICJMYXQiID0gIlkiKQ0KDQptZXRyb1JpZGVycyRUaW1lLlBlcmlvZCA9IE5VTEwNCm1ldHJvUmlkZXJzJERheS5vZi5XZWVrID0gTlVMTA0KbWV0cm9SaWRlcnMkSG9saWRheSA9IE5VTEwNCm1ldHJvUmlkZXJzJE1vbnRoID0gTlVMTA0KbWV0cm9SaWRlcnMkWWVhciA9IE5VTEwNCm1ldHJvUmlkZXJzJEF2Zy5EYWlseS5FbnRyaWVzLlJvdW5kZWQgPSBOVUxMDQoNCiNtZXRyb1JpZGVycyA9IG1ldHJvUmlkZXJzIHw+DQogI3JlbmFtZSgiU3RhdGlvbiIgPSAiw68uLlN0YXRpb24iKQ0KDQptZXRyb1IxIDwtIG1ldHJvUmlkZXJzIHw+DQogIGZpbHRlcihTZXJ2aWNldHlwZSA9PSAiV2Vla2RheSIpIHw+DQogIGRkcGx5KCJTdGF0aW9uIiwgbnVtY29sd2lzZShzdW0pKQ0KDQpNRVRSTyA8LSBtZXJnZSh4ID0gbWV0cm9SMSwgeSA9IG1ldHJvQWRkeSwgYnkgPSAiU3RhdGlvbiIpDQoNCmdsaW1wc2UoTUVUUk8pDQoNCmBgYA0KDQpDbGVhbmluZyBiaWtlIGRhdGENCg0KYGBge3J9DQpiaWtlUjEgPSBzZXB0X3JhdyAlPiUgc2VsZWN0KHN0YXJ0ZWRfYXQsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKSAlPiUgbmEub21pdCgpICU+JSBtdXRhdGUoc3RhcnRfZGF0ZT1hcy5EYXRlKHN0YXJ0ZWRfYXQpKSAlPiUgc2VsZWN0KHN0YXJ0X2RhdGUsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKQ0KDQpiaWtlUjIgPSBiaWtlUjEgJT4lIHN0X2FzX3NmKGNvb3Jkcz1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycz00MzI2KQ0KDQpzdF9jcnMobmVpZ2gkZ2VvbWV0cnlbMV0pDQoNCmJpa2VSMyA9IGJpa2VSMiAlPiUgc3Rfam9pbihuZWlnaCkNCg0KDQogDQojY29kZSBmb3IgcG9zc2libGUgZnV0dXJlIG1hcHBpbmcgDQojZGYxX3Nfc2YgPSBkZjFfcyAlPiUgc3RfYXNfc2YoY29vcmRzID1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycyA9IDQzMjYpDQpgYGANCg0KYGBge3J9DQpNZXRyb01hcCA8LSBzdF9hc19zZihNRVRSTywgY29vcmRzID0gYygiTG9uIiwgIkxhdCIpLCBjcnMgPTQzMjYpDQoNCk1ldHJvTWFwMiA8LSBNZXRyb01hcCAlPiUNCiAgc3Rfam9pbihuZWlnaCkgJT4lIG5hLm9taXQoKSAlPiUNCiAgZGRwbHkoImNvZGUiLCBudW1jb2x3aXNlKHN1bSkpDQpgYGANCg0KDQpgYGB7cn0NCg0KbmVpZ2gxID0gbmVpZ2ggJT4lIHNlbGVjdChjb2RlLCBnZW9tZXRyeSkNCg0KYmlrZVI0ID0gYmlrZVIzICU+JSBzZWxlY3Qoc3RhcnRfZGF0ZSwgY29kZSwgZ2VvbWV0cnkpICU+JSBzdF9kcm9wX2dlb21ldHJ5KCkNCg0KYmlrZVI1ID0gbmVpZ2gxICU+JSBmdWxsX2pvaW4oYmlrZVI0KSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wOScpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xMCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yNCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0zMCcpKQ0KYGBgDQoNCmBgYHtyfQ0KI3Bsb3QobmVpZ2gpDQoNCmJpa2VSNiA9IGRhdGEuZnJhbWUodGFibGUoYmlrZVI1JGNvZGUpKSAlPiUgcmVuYW1lKGNvZGU9VmFyMSkgJT4lIGZ1bGxfam9pbihiaWtlUjUpICU+JSBzZWxlY3QoY29kZSwgRnJlcSwgZ2VvbWV0cnkpICU+JSBkaXN0aW5jdCgpICU+JSBuYS5vbWl0KCkNCg0KYmlrZVI3ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoYmlrZV9mcmVxID0gRnJlcSkNCg0KTWV0cm9NYXAzID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShtZXRyb19mcmVxID0gRW50cmllcykNCg0KbWV0cm9fYmlrZV9kZiA9IGJpa2VSNyAlPiUgZnVsbF9qb2luKE1ldHJvTWFwMykgJT4lIG11dGF0ZShtZXRyb19mcmVxID0gcmVwbGFjZV9uYShtZXRyb19mcmVxLCAwKSkNCg0KI2Jpa2VSNyA9IGJpa2VSNSAlPiUgY291bnQoY29kZSwgc3RhcnRfZGF0ZSkNCg0KI3Bsb3QoYmlrZVI2KQ0KYGBgDQoNCmBgYHtyfQ0KYmlrZVI4ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoZnJlcSA9IEZyZXEpICU+JSBtdXRhdGUodHJhbnNwb3J0ID0gJ2Jpa2UnKQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDIgJT4lIHNlbGVjdChFbnRyaWVzLCBjb2RlKSAlPiUgcmVuYW1lKGZyZXEgPSBFbnRyaWVzKSAlPiUgbXV0YXRlKHRyYW5zcG9ydCA9ICdtZXRybycpDQoNCmNvZGUgPSBjKCJOMSIsICJOMTAiLCAiTjExIiwgIk4xNCIsICJOMTUiLCAiTjE2IiwgIk4yIiwgIk4yMCIsICJOMjEiLCAiTjIyIiwgIk4yNiIsICJOMjciLCAiTjI4IiwgIk4zIiwgIk4zMiIsICJOMzMiLCAiTjM0IiwgIk4zNiIsICJOMzciLCAiTjQiLCAiTjQwIiwgIk40MSIsICJONDUiLCAiTjQ2IiwgIk40NyIsICJONDkiLCAiTjUiLCAiTjUwIiwgIk41MSIsICJONiIsICJOOCIpDQoNCmZyZXEgPSBjKDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDApDQoNCnRyYW5zcG9ydCA9IGMoJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJykNCg0KbWV0cm9FeHRyYSA9IGRhdGEuZnJhbWUoY29kZSwgZnJlcSwgdHJhbnNwb3J0KQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDQgJT4lIHJiaW5kKG1ldHJvRXh0cmEpDQoNCm1ldHJvX2Jpa2VfZGYyID0gYmlrZVI4ICU+JSBmdWxsX2pvaW4oTWV0cm9NYXA0KQ0KDQpgYGANCg0KDQojIyBNYXBwaW5nIE1ldHJvDQoNCmBgYHtyfQ0KZW50cmFuY2VzPXN0X3JlYWQoaGVyZSgiTWV0cm9fU3RhdGlvbl9FbnRyYW5jZXNfaW5fREMuZ2VvanNvbiIpKSAlPiUgY2xlYW5fbmFtZXMoKQ0KDQpjbGFzcyhlbnRyYW5jZXMpDQoNCnBsb3QoZW50cmFuY2VzKQ0KYGBgDQoNCiMjIE1hcHBpbmcgQmlrZSBEYXRhDQoNCg0KYGBge3J9DQpjaGFydHMgPC0gZ2dwbG90KG1ldHJvX2Jpa2VfZGYyLCBhZXMoZmlsbD10cmFuc3BvcnQsIHk9ZnJlcSwgeD1jb2RlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0nZG9kZ2UnLCBzdGF0PSdpZGVudGl0eScpDQoNCmdncGxvdGx5KGNoYXJ0cykNCmBgYA0KDQo=
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed